<?php
// +----------------------------------------------------------------------
// | title: 标题注释
// +----------------------------------------------------------------------
// | Author: TZ.Leong
// +----------------------------------------------------------------------
// | Date: 2019/7/3 20:30
// +----------------------------------------------------------------------
use app\single\model\PayModel;
use app\single\model\RoleMailModel;
use app\single\model\VarModel;
use think\facade\Log;
use think\facade\Cache;
use cmf\lib\Http;


/**
 * @param $url
 * @param array $param
 * @param int $timeOut
 * @param string $protocol
 * @param bool $debug
 * @return bool|string
 * @throws Exception
 */
function get($url, array $param = array(), int $timeOut = 10, string $protocol = "http", bool $debug = false)
{
    //参数是一个数组
    if (!is_array($param))
        throw new \Exception("参数必须为array");
    //组装get提交数据
    if (!empty($param)) {
        $p = '';
        foreach ($param as $key => $value) {
            $p = $p . $key . '=' . $value . '&';
        }
        //是否拼装? / &
        if (preg_match('/\?[\d\D]+/', $url)) {//matched ?c
            $p = '&' . $p;
        } else {
            $p = '?' . $p;
        }
        //替换多余的连接符
        $p = preg_replace('/&$/', '', $p);
        $url = $url . $p;
    }
    //开始请求
    $httph = curl_init($url);
    curl_setopt($httph, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($httph, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($httph, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($httph, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
    curl_setopt($httph, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($httph, CURLOPT_HEADER, 0);
    curl_setopt($httph, CURLOPT_TIMEOUT, $timeOut);
    curl_setopt($httph, CURLOPT_CONNECTTIMEOUT, 2);//2秒链接不上，就断开
    // disable 100-continue
    curl_setopt($httph, CURLOPT_HTTPHEADER, array('Expect:'));
    //https请求
    if ("https" == $protocol) {
        curl_setopt($httph, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($httph, CURLOPT_SSL_VERIFYHOST, false);
    } elseif (is_array($protocol) && $protocol["type"] == "cookie") {
        curl_setopt($httph, CURLOPT_COOKIE, $protocol["params"]);
    }
    $result = curl_exec($httph);
    if (empty($result) && $debug) {
        echo 'result->' . $result . "->" . print_r(curl_getinfo($httph), true) . print_r(curl_error($httph), true) . PHP_EOL;
    }
    curl_close($httph);
    return $result;
}


/**
 * @throws Exception
 */
function PHP2Erlang($type, $data = array(), $jsonData = "")
{
    if (!is_array($data)) {
        throw new Exception("data type must be array");
    }

    $config = Cache::store("file")->get("server_info");
    //通讯端口号
    $port = (int) $config["port"];
    $is_https = (int) $config["is_https"] ?? 0;
    // $url_prefix = "http";
    $proto = "http";
    if ($is_https == 1) {
        // $url_prefix = "https";
        $proto = "https";
    }

    $url = $proto . "://127.0.0.1";
    if (empty($jsonData)) {
        $jsonData = empty($data) ? "{}" : "{" . implode(",", $data) . "}";
    }


    //请求参数
    $nowTime = time();
    $paramArr = array("platform" => PLATFORM, "server_num" => PLAT_SERVER_ID, "do" => $type, "data" => $jsonData, "time" => $nowTime);
    //增加token参数
    $paramArr["token"] = strtolower(md5(join("", $paramArr) . config("secure.SERVER_BACKGROUND_KEY")));
   
    //todo: 更新版本的时候需要改动 
     // $paramArr["token"] = strtolower(md5(join("", $paramArr) . config("secure.SERVER_BACKGROUND_KEY")));

    //使用http - get提交数据
    try {
        $response = get($url . ":" . $port . "/background", $paramArr, 20, $proto, true);
        
        if (empty($response)) {
            Log::write("请求url" . $url . ":" . $port . "/background" . "请求参数" . json_encode($paramArr, true) . "返回结果:" . $response);
            return array("code" => BACKGROUND_PARAM_ERROR, "data" => "请求异常,response empty");
        }
        $resArr = json_decode($response, true);
        if ($resArr["code"] !== BACKGROUND_SUCCESS) {
            Log::error(json_encode($resArr,true) ."\n" . $url . ":" . $port . "/background?" . urldecode(http_build_query($paramArr))) ;
        }
        return $resArr;
    } catch (\Exception $e) {
        Log::error("请求异常\n" . $url . ":" . $port . "/background?" . urldecode(http_build_query($paramArr)) . PHP_EOL);
        return array("code" => BACKGROUND_PARAM_ERROR, "data" => "请求异常");
    }

}


/**
 * 获取当前服所有平台号
 * @return array
 */
function getPlatformLists(): array
{
    $varModel = new VarModel();
    preg_match_all('/<<.*?>>/is', $varModel->getValue("platform_lists"), $matches);
    $platArr = array();
    foreach ($matches[0] as $platform) {
        $platArr[] = ascii2string($platform);
    }
    return $platArr;
}

/**
 * ascii码转中文
 * @param string $ascii ascii码(<<228,184,173,229,155,189>>)
 * @return string
 */
function ascii2string(string $ascii = ""): string
{
    //去掉<< 和>>
    $ascii = str_replace(array("<<", ">>"), array("", ""), $ascii);
    //切割成一个数组
    $asciiArr = explode(",", $ascii);
    //循环拼装成中文
    $string = "";
    foreach ($asciiArr as $v) {
        $string .= chr($v);
    }
    return $string;
}

/**
 * 把服务端的物品字符串转成数组
 * @param $strings string
 * @return array
 */
function string2array(string $strings): array
{
    $infoArr = array();
    //先正则删掉,[{xxx}]}的内容
//    $string = preg_replace("/,\[\{.*?\}\]\}/is","",$string);
    //使用正则切割成{1,2,3}这样的数组
    preg_match_all('/\{\d+,(-?)\d+}/i', $strings, $matches);
    foreach ($matches[0] as $info) {
        //去掉花括号
        $info = str_replace(array("{", "}"), "", $info);
        //切割成数组
        $itemArr = explode(",", trim($info));
        if (count($itemArr) == 2) {
            $infoArr[] = $itemArr;
        }
    }
    return $infoArr;
}

/**
 * 给玩家发送邮件奖励
 * @param int $playerId 玩家ID
 * @param array $itemArr 奖励附件；array(array("code" => 2,"num" => 1000),array("code" => 2,"num" => 1000))
 * @param string $title 邮件标题
 * @param string $content 邮件内容
 * @param int $mail_type 邮件类型
 * @return bool         true - false
 */
function sendItemReward(int $playerId, array $itemArr, string $title, string $content, int $mail_type): bool
{
    //玩家角色ID必须
    if (empty($playerId))
        return false;
    //获取邮件附件
    $attachmentArr = attachment($itemArr);
    //附件格式不正确
    if (empty($attachmentArr)) {
        return false;
    }
    $mailModel = new RoleMailModel();
    $mailResultId = $mailModel->sendMail($playerId, newattachment($itemArr), $title, $content, $mail_type);


    //    Log::write("debug mailResultIds:" . $mailResultIds);
    //把邮件ID通知服务端处理
//    if ($mailResultIds) {
//        //组装玩家ID和邮件ID
//        $operate = "[" . rtrim($mailResultIds, ",") . "]";
//        PHP2Erlang(5, [], $operate);
//        return true;
//    }
    $mail_data = [
        "mail_kind" => $mail_type,
        'type' => $mail_type,
        'send_time' => time(),
        "expire_time" => time() + 86400 * 30,
        'to_rid' => $playerId,
        "title" => string2ascii($title),
        "content" => string2ascii($content),
        "item" => newattachment($itemArr)
    ];

    $serdata = [
        (int) $mail_data["mail_kind"],
        (int) $mail_data["type"],
        (int) $mail_data["send_time"],
        (int) $mail_data["expire_time"],
        (int) $mail_data["to_rid"],
        $mail_data["title"],
        $mail_data["content"],
        $mail_data["item"]
    ];

    try {
        $res = PHP2Erlang(BACKGROUND_MAIL, $serdata);
    } catch (Exception $e) {
        Log::write("php2 erlang error" . $e->getMessage(), "error");
        return false;
    }
    if ($res["code"] !== 0) {
        return false;
    } else {
        return true;
    }


}

/**
 * 组装邮件附件
 * @param $itemArr  array(array("code" => 2,"num" => 1000),array("code" => 2,"num" => 1000))
 * @return array
 */
function attachment(array $itemArr): array
{
    //奖励必须是一个数组
    if (!is_array($itemArr)) {
        return array();
    }
    //要把附件修改成二维数组
    $itemArr = isset($itemArr["code"]) ? array($itemArr) : $itemArr;
    //拼装附件
    $gifts = array();
    if (count($itemArr) > 5) {
        //切割成5个一组
        $itemArr = array_chunk($itemArr, 5);
        foreach ($itemArr as $i => $giftArr) {
            foreach ($giftArr as $vo) {
                //格式{code,num}
                $content = "{" . $vo["code"] . "," . $vo["num"] . "}";
                $gifts[$i] = isset($gifts[$i]) ? $gifts[$i] . "," . $content : $content;
            }
        }
    } else {
        foreach ($itemArr as $vo) {
            //格式{code,num}
            $content = "{" . $vo["code"] . "," . $vo["num"] . "}";
            $gifts[0] = isset($gifts[0]) ? $gifts[0] . "," . $content : $content;
        }
    }
    return $gifts;
}

/**
 * @param  $itemArr
 * @return string
 */
function newattachment($itemArr): string
{
    if (empty($itemArr)) {
        return '[]';
    }
    //奖励必须是一个数组
    if (!is_array($itemArr)) {
        return '{}';
    }
    //要把附件修改成二维数组
    $result = '[';
    foreach ($itemArr as $key => $item) {
        if ($key > 0) {
            $result .= ',';
        }
        $result .= '{' . $item['code'] . ',' . $item['num'] . '}';
    }
    $result .= ']';
    return $result;
}

/**
 * 模拟充值元宝
 * @param $playerId
 * @param $gold
 * @param int $chargeType
 * @param array $payData
 * @return bool
 * @throws \think\exception\PDOException
 */
function moniPay($playerId, $gold, int $chargeType = 1, array $payData = array()): bool
{
    //给玩家增加元宝数
    $model = new PayModel();
    if ($model->addPay($playerId, $chargeType, $gold, 0, $payData)) {
        return true;
    }
    return false;
}

/**
 * 获取当前服版本
 * @return string
 */
function getVer(): string
{
    static $_config = [];
    if (empty($_config)) {
        $_config = Cache::store("file")->get("server_info");
    }
    if (isset($_config["version"]) && $_config["version"]) {
        return $_config["version"];
    }
    return GAME_NAME;
}
